you are working in web application testing domain and are interested in test automation, you might have used, come across or heard about PageObject Model in test automation. If you haven't heard of it, it might be a good idea to read this article. In nutshell, a separate class is created for every page / screen of the application in the PageObject model. This class exposes methods to represent all the operations a user can perform on various elements on the page. For example, a class to represent LoginPage might have methods to enter userName, password and click on submit button. Tests can use this class to interact with the page instead of duplicating elements everywhere in the test scripts.
PageObject essentially decouples UI from the tests and as a result makes test automation suite a bit more maintainable. In my opinion, if you are not doing anything else, PageObject Model is at least something you should implement in your test automation projects to decouple UI from the tests.
This is all fine and PageObject model usually works. However, in the context of web applications, we often come across common components or parts of the page which are shared on some or all the pages. How do we handle common components like header / footer / sidebars / widgets etc with PageObjects model?
A simple (and bad) way to solve this problem would be to ignore it as a problem to solve and copy paste elements and their methods on all the pages. This is a sure way to get into the maintenance nightmare and will have potential to put you on the story of Jim :-)
However, there are plenty of good ways to solve this problem. Let us examine the approaches I have used in past to solve this problem
Handling common parts with inheritance
Inheritance in the context of OOP is often used for code reuse or to establish subtype from an existing type. In the context of solving this problem, we can't really establish subtype kind of relationship in the pages, so our focus is on reusing the code with inheritance.
Let's say our application has common header, footer and sidebar on all the pages. To represent this in the PageObject Model without duplicating them on all the pages, we create a BasePage class with all the common parts. This BasePage class might look similar to the following class definition
Class BasePage { // common elements & methods for header // common elements & methods for footer // common elements & methods for sidebars //� and so on }
Now all the pages with common header, footer and sidebar will be inherited from this class. This is a simple and effective way to remove code duplication in PageObject model to some extent.
This approach can also be used effectively with many types of BasePages. For example, if header / footer / navigation etc are different for user who is logged in the system, we can create BasePageForLoggedInUser and so on.
Classes to represent Pages can focus on specific bits pages are accomplishing and everything else can be inherited from the base classes.
This approach works, but it is not perfect.
Handling slight variations or unique pages might become tricky. For example, if header / footer are slightly different for few promotional pages, it will require one more BaseClass. On the same lines, if it is possible to control layout / content of the pages with the widgets, it might be difficult to define pages in advance.
Handling common parts with composition
Composition, In my opinion is a better approach. In OOP, composition is often used to represent "has a" relationship. If you think about pages, screens and shared components like header, footer etc, "has a" relation makes more sense. For example, it is very natural to say that PaymentPage has a navigation and footer whereas AccountPage has sidebar and footer.
In this approach, instead of creating a base page with all the shared components, an object is created for every component which can be shared on multiple pages. Things like header, footer, sidebars etc are created as separate classes on the lines of
Class Header{ // stuff related to header } Class Footer { // stuff related to footer } Class SideBar { // stuff related to sidebar }
Now pages can use these components as needed instead of relying on the inheritance or duplicating code. A home page with header and footer might look on the lines of
Class HomePage { Header header; Footer footer; // home page related stuff }
This approach IMO is better than inheritance for many reasons. Code is much easier to understand with the composition than inheritance. Header object is instantiated in the HomePage class and so I know that HomePage has a header. With inheritance, it's not visible and readable. With composition it is possible to create any page you want by instantiating whatever make sense. With inheritance, it might be possible to have duplicate code in various BasePages, a bit more complicated multi-level inheritance or a combination of both.
So what am I using these days - well whatever make sense :-) Have you faced similar issue in your experience? Please leave your comments and let us know how you have approached it. Thank you for sharing this in your network :-)